﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.StopZero.CApStopZeroProgressReporter
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.StopZero;

public class CApStopZeroProgressReporter
{
  private const int StartProgress = 10;
  private const int MotionVolumeProgress = 10;
  private readonly int AllLocationsProgress;
  private ITxRoboticLocationOperation _startLocation;
  private ITxRoboticLocationOperation _endLocation;
  private Action<CApStopZeroProgressReporterData> _progressSetter;
  private CApStopZeroProgressReporterData _currentProcessData;
  private Dictionary<ITxRoboticLocationOperation, double> _locationProgress;

  public CApStopZeroProgressReporter(
    ITxRoboticLocationOperation start,
    ITxRoboticLocationOperation end,
    Action<CApStopZeroProgressReporterData> progressSetter)
  {
    this._startLocation = start;
    this._endLocation = end;
    this._progressSetter = progressSetter;
    this._currentProcessData = new CApStopZeroProgressReporterData();
    this.AllLocationsProgress = 80 /*0x50*/;
    this.InitializeLocationsProgress();
  }

  public void ReportLocationProgress(ITxRoboticLocationOperation location, bool updateStatusMessage)
  {
    if (location == null || !this._locationProgress.ContainsKey(location))
      return;
    this._currentProcessData.CurrentLocation = location;
    if (updateStatusMessage)
      this.ReportProgressIncrease(0.0);
    else
      this.ReportProgressIncrease(this._locationProgress[location]);
  }

  public void ReportMotionVolumeProgress(bool updateStatusMessage)
  {
    if (!updateStatusMessage)
      this.ReportProgressIncrease(10.0);
    this._currentProcessData.CurrentLocation = (ITxRoboticLocationOperation) null;
    this._currentProcessData.GeneratingVolume = true;
    this.ReportProgressIncrease(0.0);
  }

  public void ReportStart()
  {
    this.ReportProgressIncrease(10.0);
    this._currentProcessData.Initialized = true;
  }

  public void ReportEnd()
  {
    this._currentProcessData.Reset();
    this.ReportProgress(this._currentProcessData);
  }

  public void ReportNonPrgress() => this.ReportProgress(this._currentProcessData);

  private void ReportProgress(CApStopZeroProgressReporterData progressData)
  {
    if (this._progressSetter != null)
      this._progressSetter(progressData);
    Application.DoEvents();
  }

  private void ReportProgressIncrease(double progressIncrease)
  {
    this._currentProcessData.CurrentProgress += progressIncrease;
    this.ReportProgress(this._currentProcessData);
  }

  private void InitializeLocationsProgress()
  {
    this._locationProgress = new Dictionary<ITxRoboticLocationOperation, double>();
    List<ITxObject> segmentLocations = this.GetSegmentLocations();
    double segmentDuration;
    if (!this.GetLocationsDurations(segmentLocations, out segmentDuration))
      segmentDuration = this.GetAllLocationsDistances(segmentLocations);
    this.NormalizeLocationsProgress(segmentLocations, segmentDuration);
  }

  private List<ITxObject> GetSegmentLocations()
  {
    return ((IEnumerable<ITxObject>) ((ITxObjectCollection) this._startLocation.ParentRoboticOperation).GetAllDescendants((ITxTypeFilter) new TxTypeFilter(typeof (ITxRoboticLocationOperation)))).SkipUntil<ITxObject>((Func<ITxObject, bool>) (location => location != this._startLocation)).TakeUntil<ITxObject>((Func<ITxObject, bool>) (location => location != this._endLocation)).ToList<ITxObject>();
  }

  private bool GetLocationsDurations(List<ITxObject> riskLocations, out double segmentDuration)
  {
    segmentDuration = 0.0;
    ITxRoboticLocationOperation location1 = this._startLocation;
    foreach (ITxRoboticLocationOperation riskLocation in riskLocations)
    {
      double duration = ((ITxOperation) riskLocation).Duration;
      if (duration == 0.0 && this.GetDistance(location1, riskLocation) > 1E-07)
      {
        this._locationProgress.Clear();
        return false;
      }
      this._locationProgress.Add(riskLocation, duration);
      segmentDuration += duration;
      location1 = riskLocation;
    }
    return true;
  }

  private double GetAllLocationsDistances(List<ITxObject> riskLocations)
  {
    double locationsDistances = 0.0;
    ITxRoboticLocationOperation location1 = this._startLocation;
    foreach (ITxRoboticLocationOperation riskLocation in riskLocations)
    {
      double distance = this.GetDistance(location1, riskLocation);
      this._locationProgress.Add(riskLocation, distance);
      locationsDistances += distance;
      location1 = riskLocation;
    }
    return locationsDistances;
  }

  private double GetDistance(
    ITxRoboticLocationOperation location1,
    ITxRoboticLocationOperation location2)
  {
    TxVector translation1 = (location1 as ITxLocatableObject).AbsoluteLocation.Translation;
    TxVector translation2 = (location2 as ITxLocatableObject).AbsoluteLocation.Translation;
    return Math.Sqrt(Math.Pow(translation1.X - translation2.X, 2.0) + Math.Pow(translation1.Y - translation2.Y, 2.0) + Math.Pow(translation1.Z - translation2.Z, 2.0));
  }

  private void NormalizeLocationsProgress(List<ITxObject> riskLocations, double segmentDuration)
  {
    foreach (ITxRoboticLocationOperation riskLocation in riskLocations)
    {
      double num = this._locationProgress[riskLocation] / segmentDuration * (double) this.AllLocationsProgress;
      this._locationProgress[riskLocation] = num;
    }
  }
}
